package com.bullsora.kindlerss.business;

import com.bullsora.kindlerss.model.Subscription;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ScheduledFuture;

/**
 * @author Sorin Buliarca
 */
@Component
public class SubscriptionsTasksRegistry {

  public static final Log LOG = LogFactory.getLog(SubscriptionsTasksRegistry.class);
  
  @Autowired
  private TaskScheduler taskScheduler;

  @Autowired
  private SubscriptionsService subscriptionsService;

  private Map<Long, ScheduledFuture> tasksMap = new HashMap<Long, ScheduledFuture>();

  public void init() {
    LOG.info("Initializing subscription tasks");
    
    List<Subscription> allSubscriptions = subscriptionsService.findAllSubscriptions();
    for (Subscription subscription : allSubscriptions) {
      scheduleSubscriptionTask(subscription);
    }
  }
  
  public void destroy() {
    LOG.info("Destroying subscription tasks");
    for (ScheduledFuture task : tasksMap.values()) {
      task.cancel(false);
    }
  }  

  public void scheduleSubscriptionTask(Subscription subscription) {
    LOG.info("Scheduling subscription task for subscription " + subscription.getId());
    ScheduledFuture existingScheduledFuture = tasksMap.get(subscription.getId());
    if (existingScheduledFuture != null) {
      existingScheduledFuture.cancel(false);
    }

    ScheduledFuture newScheduledFuture = taskScheduler.schedule(
        new FulfillSubscriptionTask(subscription.getId()),
        new CronTrigger(subscription.getSendCronExpression())
    );

    tasksMap.put(subscription.getId(), newScheduledFuture);
  }

  private class FulfillSubscriptionTask implements Runnable {

    private Long subscriptionId;

    private FulfillSubscriptionTask(Long subscriptionId) {
      this.subscriptionId = subscriptionId;
    }

    @Override
    public void run() {
      subscriptionsService.sendNewEntries(subscriptionId);
    }
  }

}
